package cn.chinaflame.pagodas.service;

import static cn.chinaflame.pagodas.constant.Sysconst.POSITIONS;
import static cn.chinaflame.pagodas.constant.Sysconst.MAXPILLARS;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;

import cn.chinaflame.pagodas.Result.Result;
import cn.chinaflame.pagodas.constant.Sysconst;
import cn.chinaflame.pagodas.dto.PaProductDto;
import cn.chinaflame.pagodas.dto.PaProductPositionDto;
import cn.chinaflame.pagodas.entity.PaProduct;
import cn.chinaflame.pagodas.entity.PaProductArea;
import cn.chinaflame.pagodas.entity.PaProductPoint;
import cn.chinaflame.pagodas.entity.PaProductPosition;
import cn.chinaflame.pagodas.enums.CodeEnum;
import cn.chinaflame.pagodas.repository.PaProductAreaRepository;
import cn.chinaflame.pagodas.repository.PaProductPointRepository;
import cn.chinaflame.pagodas.repository.PaProductPositionRepository;
import cn.chinaflame.pagodas.repository.PaProductRepository;
import cn.chinaflame.pagodas.utils.DateTimes;
import cn.chinaflame.pagodas.utils.ParamPreconditions;
import static cn.chinaflame.pagodas.constant.Sysconst.FLOORINSTEADAREA;
/**
 * 商品位置service
 *
 * @author created by boming
 * @date 2018年1月6日 下午2:35:17
 */
@Service
public class PaProductPositionService {

	
    private static final Logger log = LoggerFactory.getLogger(PaProductPositionService.class);

    @Autowired
    private PaProductPositionRepository paProductPositionRepository;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private PaProductAreaRepository paProductAreaRepository;
    @Autowired
    private PaProductService paProductService;
    @Autowired
    private PaProductPointRepository paProductPointRepository;
    @Autowired
    private PaProductRepository paProductRepository;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private PaProductPointService paProductPointService;

    /**
     * 查询商品位置列表
     *
     * @param pageIndex
     * @param pageSize
     * @param id
     * @param name
     * @return
     */
    public Result<List<PaProductPositionDto>> queryList(Integer pageIndex, Integer pageSize, String id, String name, String areaId) {
        log.info("查询商品位置列表pageIndex:{},pageSize:{},id:{},name:{},areaId:{}", pageIndex, pageSize, id, name, areaId);
        if (commonService.paginationSupport(pageIndex, pageSize))
            return queryListByPage(pageIndex, pageSize, id, name, areaId);
        List<PaProductPosition> positionList = paProductPositionRepository.findAll(new Specification<PaProductPosition>() {
            @Override
            public Predicate toPredicate(Root<PaProductPosition> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = Lists.newArrayList();
                list.add(cb.equal(root.get("state").as(String.class), Sysconst.ENABLED_TRUE));
                if (!Strings.isNullOrEmpty(id))
                    list.add(cb.equal(root.get("id").as(String.class), id));
                if (!Strings.isNullOrEmpty(name))
                    list.add(cb.like(root.get("name").as(String.class), name));
                if (!Strings.isNullOrEmpty(areaId))
                    list.add(cb.equal(root.get("areaId").as(String.class), areaId));
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        });
        List<PaProductPositionDto> dtoList = Lists.newArrayList();
        for (PaProductPosition position : positionList) {
            PaProductPositionDto dto = new PaProductPositionDto();
            BeanUtils.copyProperties(position, dto);
            PaProductArea ppa = paProductAreaRepository.findOne(position.getAreaId());
            dto.setAreaName(ppa.getName());
            dto.setAreaNo(ppa.getAreaNo());
            dtoList.add(dto);
        }
        return Result.create(dtoList);
    }
    /*new_edition 新方法*/

    /**
     * 查询商品位置列表
     *
     * @param pageIndex
     * @param pageSize
     * @param id
     * @param name
     * @return
     */
    public Result<List<PaProductPositionDto>> queryList1(Integer pageIndex, Integer pageSize, String id, String name, String areaId, String productId) {
        log.info("查询商品位置列表pageIndex:{},pageSize:{},id:{},name:{},areaId:{},productId:{}", pageIndex, pageSize, id, name, areaId, productId);
        if (commonService.paginationSupport(pageIndex, pageSize))
            return queryListByPage(pageIndex, pageSize, id, name, areaId);
        List<PaProductPosition> positionList = paProductPositionRepository.findAll(new Specification<PaProductPosition>() {
            @Override
            public Predicate toPredicate(Root<PaProductPosition> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = Lists.newArrayList();
                list.add(cb.equal(root.get("state").as(String.class), Sysconst.ENABLED_TRUE));
                if (!Strings.isNullOrEmpty(id))
                    list.add(cb.equal(root.get("id").as(String.class), id));
                if (!Strings.isNullOrEmpty(name))
                    list.add(cb.like(root.get("name").as(String.class), name));
                if (!Strings.isNullOrEmpty(areaId))
                    list.add(cb.equal(root.get("areaId").as(String.class), areaId));
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        });
        List<PaProductPositionDto> dtoList = Lists.newArrayList();
        if (!Strings.isNullOrEmpty(productId)) {
            //查询商品位置的墙信息
            PaProduct product = paProductRepository.getOne(productId);
            //数组放到list里面
            List<String> positions = Arrays.asList(product.getPositionIds().split(","));
            for (PaProductPosition position : positionList) {
                //根据根据位置id获得库存
                int stock = paProductPointService.getStock(position.getId());
                //比较当前位置ID是否对应商品精确位置
                if (positions.contains(position.getId()) && stock > 0) {
                    PaProductPositionDto dto = new PaProductPositionDto();
                    BeanUtils.copyProperties(position, dto);
                    //根据区域编号找到对应的区域信息
                    PaProductArea ppa = paProductAreaRepository.findOne(position.getAreaId());
                    if(StringUtils.isNotBlank(ppa.getName()) && ppa.getName().length() >= 2) {
                    	dto.setAreaName(Integer.parseInt(ppa.getName().substring(0,2))+FLOORINSTEADAREA);
                    }
                    if(StringUtils.isNotBlank(dto.getName()) && dto.getName().length() >= 2) {
                    	dto.setName(Integer.parseInt(dto.getName().substring(0, 2))+dto.getName().substring(2));
                    }
                    dtoList.add(dto);
                }
            }
        } else {
            for (PaProductPosition position : positionList) {
                PaProductPositionDto dto = new PaProductPositionDto();
                BeanUtils.copyProperties(position, dto);
                PaProductArea ppa = paProductAreaRepository.findOne(position.getAreaId());
                dto.setAreaName(ppa.getName());
                dtoList.add(dto);
            }
        }
        return Result.create(dtoList);
    }

    /**
     * 查询商品位置列表
     *
     * @param pageIndex
     * @param pageSize
     * @param id
     * @param name
     * @return
     */
    public Result<List<PaProductPositionDto>> queryListByPage(Integer pageIndex, Integer pageSize, String id, String name, String areaId) {
        log.info("查询商品位置列表pageIndex:{},pageSize:{},id:{},name:{},areaId:{}", id, name, areaId);
        Pageable p = new PageRequest(pageIndex - 1, pageSize, new Sort(Direction.DESC, "updatetime"));
        Page<PaProductPosition> entityPage = paProductPositionRepository.findAll(new Specification<PaProductPosition>() {
            @Override
            public Predicate toPredicate(Root<PaProductPosition> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = Lists.newArrayList();
                list.add(cb.equal(root.get("state").as(String.class), Sysconst.ENABLED_TRUE));
                if (!Strings.isNullOrEmpty(id))
                    list.add(cb.equal(root.get("id").as(String.class), id));
                if (!Strings.isNullOrEmpty(name))
                    list.add(cb.like(root.get("name").as(String.class), name));
                if (!Strings.isNullOrEmpty(areaId))
                    list.add(cb.equal(root.get("areaId").as(String.class), areaId));
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        }, p);
        List<PaProductPosition> positionList = entityPage.getContent();
        List<PaProductPositionDto> dtoList = Lists.newArrayList();
        for (PaProductPosition position : positionList) {
            PaProductPositionDto dto = new PaProductPositionDto();
            BeanUtils.copyProperties(position, dto);
            PaProductArea ppa = paProductAreaRepository.findOne(position.getAreaId());
            dto.setAreaName(ppa.getName());
            dtoList.add(dto);
        }
        return Result.createPage(dtoList, entityPage.getTotalElements());
    }

    /**
     * 添加商品位置
     *
     * @param name
     * @param areaId
     * @return
     */
    public PaProductPositionDto add(String name, String areaId, String cameraIp) {
        log.info("添加商品位置name:{},areaId:{}", name, areaId);
        ParamPreconditions.checkNotEmpty(name, CodeEnum.FAIL.getCode(), "商品位置名称不能为空");
        ParamPreconditions.checkNotEmpty(areaId, CodeEnum.FAIL.getCode(), "商品位置区域不能为空");
        ParamPreconditions.checkNotEmpty(cameraIp, CodeEnum.FAIL.getCode(), "摄像头位置不能为空");
        List<PaProductPositionDto> listdto = queryList(null, null, null, name, areaId).getData();
        ParamPreconditions.checkArgument(listdto == null || listdto.size() == 0, CodeEnum.FAIL.getCode(), "商品位置区域不能重复");
        String id = idGeneratorService.generateProductPositionId();
        String positionNo = extractNoByStr(name);
        positionNo = positionNo.length() < 2 ? "0" + positionNo : positionNo;
        String positionLoc = listdto.get(0).getAreaNo()+ positionNo;
        PaProductPosition position = new PaProductPosition();
        position.setId(id);
        position.setName(name);
        position.setAreaId(areaId);
        position.setCameraIp(cameraIp);
        position.setPositionNo(positionLoc);
        position.setState(Sysconst.ENABLED_TRUE);
        position.setCreatetime(DateTimes.nowDateTime());
        position.setUpdatetime(DateTimes.nowDateTime());
        position = paProductPositionRepository.saveAndFlush(position);
        PaProductPositionDto dto = new PaProductPositionDto();
        BeanUtils.copyProperties(position, dto);
        return dto;
    }

    /*new_edition 新版本的添加方法*/

    /**
     * 添加商品位置
     *
     * @param name
     * @param areaId
     * @return
     */
    public PaProductPositionDto add1(String name, String areaId, String cameraIp, Integer rows, Integer cols) {
        log.info("添加商品位置name:{},areaId:{},rows:{},cols:{}", name, areaId, rows, cols);
        ParamPreconditions.checkNotEmpty(name, CodeEnum.FAIL.getCode(), "商品位置名称不能为空");
        ParamPreconditions.checkNotEmpty(areaId, CodeEnum.FAIL.getCode(), "商品位置区域不能为空");
        rows = rows == null ? 15 : rows;  //该位置安装的行数
        cols = cols == null ? 15 : cols;  //该位置安装的列数
        int default_rows = 20;
        int default_cols = 20;
        ParamPreconditions.checkArgument(rows < 99 && rows > 0, CodeEnum.FAIL.getCode(), "最大支持99行");
        ParamPreconditions.checkArgument(cols <= 99 && cols > 0, CodeEnum.FAIL.getCode(), "最大支持99列");
        /*校验位置是否被占用start*/
        PaProductArea area = paProductAreaRepository.getOne(areaId);
        String positionNo = extractNoByStr(name); //获取位置编号
        positionNo = positionNo.length() < 2 ? "0" + positionNo : positionNo;
        String positionLoc = area.getAreaNo() + positionNo;
        PaProductPosition exist = paProductPositionRepository.findByNoAndAreaId(positionLoc, areaId);
        ParamPreconditions.checkArgument(exist == null, CodeEnum.FAIL.getCode(), "位置重复");
        /*end*/
        /*创建位置对象并保存*/
        String id = idGeneratorService.generateProductPositionId();
        PaProductPosition position = new PaProductPosition();
        position.setId(id);
        position.setName(name);
        position.setAreaId(areaId);
        position.setPositionNo(positionLoc);
        position.setCameraIp(cameraIp);
        position.setState(Sysconst.ENABLED_TRUE);
        position.setCreatetime(DateTimes.nowDateTime());
        position.setUpdatetime(DateTimes.nowDateTime());
        position = paProductPositionRepository.saveAndFlush(position);
        /*保存位置行列信息start*/
        List<PaProductPoint> points = Lists.newArrayList();
        for (int i = 1; i <= default_rows; i++) {
            String row = i < 10 ? ("0" + String.valueOf(i)) : String.valueOf(i);
            for (int j = 1; j <= default_cols; j++) {
                String col = j < 10 ? ("0" + String.valueOf(j)) : String.valueOf(j);
                if (i <= rows && j <= cols) {
                    PaProductPoint point = new PaProductPoint();
                    point.setId(idGeneratorService.generatePaProductPointId());
                    point.setAreaId(areaId);
                    point.setPositionId(position.getId());
                    point.setRow(row);
                    point.setCol(col);
                    point.setStatus(Sysconst.POINT_STATUS_INSTALLED);
                    point.setLocationNo(positionLoc + row + col);
                    point.setCreatetime(DateTimes.nowDateTime());
                    point.setUpdatetime(DateTimes.nowDateTime());
                    points.add(point);
                } else {
                    PaProductPoint point = new PaProductPoint();
                    point.setId(idGeneratorService.generatePaProductPointId());
                    point.setAreaId(areaId);
                    point.setPositionId(position.getId());
                    point.setRow(row);
                    point.setCol(col);
                    point.setStatus(Sysconst.POINT_STATUS_UNINSTALL);
                    point.setLocationNo(positionLoc + row + col);
                    point.setCreatetime(DateTimes.nowDateTime());
                    point.setUpdatetime(DateTimes.nowDateTime());
                    points.add(point);
                }

            }
        }
        paProductPointRepository.save(points);
        /*保存行列信息end*/
        PaProductPositionDto dto = new PaProductPositionDto();
        BeanUtils.copyProperties(position, dto);
        return dto;
    }


    /**
     * 更新商品位置
     *
     * @param id
     * @param name
     * @return
     */
    public PaProductPositionDto update(String id, String name, String cameraIp) {
        log.info("更新商品位置id:{},name:{},cameraIp:{}", id, name, cameraIp);
        PaProductPosition area = paProductPositionRepository.findOne(id);
        ParamPreconditions.checkArgument(area != null, CodeEnum.FAIL.getCode(), "未找到记录");
        area.setName(name);
        area.setCameraIp(cameraIp);
        area.setUpdatetime(DateTimes.nowDateTime());
        area = paProductPositionRepository.saveAndFlush(area);
        PaProductPositionDto dto = new PaProductPositionDto();
        BeanUtils.copyProperties(area, dto);
        return dto;
    }
    /*new_edition 更新新版本,,,,,,,作废*/

    /**
     * 更新商品位置
     *
     * @param id
     * @param name
     * @return
     */
    public PaProductPositionDto update1(String id, String name, String cameraIp, String rows, String cols) {
        log.info("更新商品位置id:{},name:{},cameraIp:{},rows:{},cols:{}", id, name, cameraIp, rows, cols);
        PaProductPosition posittion = paProductPositionRepository.findOne(id);
        ParamPreconditions.checkArgument(posittion != null, CodeEnum.FAIL.getCode(), "未找到记录");
        /*校验位置是否存在*/
        PaProductArea area = paProductAreaRepository.getOne(posittion.getAreaId());
        String positionNo = extractNoByStr(name); //获取位置编号
        positionNo = positionNo.length() < 2 ? "0" + positionNo : positionNo;
        String positionLoc = area.getAreaNo() + positionNo;
        PaProductPosition exist = paProductPositionRepository.findByNoAndAreaId(positionLoc, area.getId());
        boolean b = exist == null || Objects.equal(exist.getId(), posittion.getId());
        ParamPreconditions.checkArgument(b, CodeEnum.FAIL.getCode(), "位置重复");
        /*校验位置是否被占用*/
        List<PaProductPoint> used = paProductPointRepository.findByPositionIdAndNonStatus(posittion.getId(), Sysconst.POINT_STATUS_INSTALLED);
        ParamPreconditions.checkArgument(used == null || used.size() == 0, CodeEnum.FAIL.getCode(), "位置使用中");
        /*更新位置行列状态*/
        String rows_n = rows.length() < 2 ? "0" + rows : rows;
        String cols_n = cols.length() < 2 ? "0" + cols : cols;
        String sql = "update pa_product_point set location_no=CONCAT(SUBSTR(location_no,1,2),'" + positionNo + "',SUBSTR(location_no,5,6)) where SUBSTR(location_no,7,2) <= '" + rows_n + "' and SUBSTR(location_no,9,2) <='" + cols_n + "' and status='" + Sysconst.POINT_STATUS_INSTALLED + "'";
        jdbcTemplate.update(sql);
        /*更新位置信息*/
        posittion.setName(name);
        posittion.setPositionNo(positionLoc);
        posittion.setCameraIp(cameraIp);
        posittion.setUpdatetime(DateTimes.nowDateTime());
        paProductPositionRepository.saveAndFlush(posittion);
        PaProductPositionDto dto = new PaProductPositionDto();
        BeanUtils.copyProperties(posittion, dto);
        return dto;
    }

    /**
     * 更新商品位置
     *
     * @param id
     * @param name
     * @return
     */
    public PaProductPositionDto update2(String id, String name, String cameraIp, String rows, String cols) {
        log.info("更新商品位置id:{},name:{},cameraIp:{},rows:{},cols:{}", id, name, cameraIp, rows, cols);
        PaProductPosition area = paProductPositionRepository.findOne(id);
        ParamPreconditions.checkArgument(area != null, CodeEnum.FAIL.getCode(), "未找到记录");
        String rows_n = rows.length() < 2 ? "0" + rows : rows;
        String cols_n = cols.length() < 2 ? "0" + cols : cols;
        String positionNo = extractNoByStr(name);
        positionNo = positionNo.length() < 2 ? "0" + positionNo : positionNo;
        PaProductArea aaa = paProductAreaRepository.getOne(area.getAreaId());
        String positionLoc = aaa.getAreaNo() + positionNo;
        String start = positionLoc + "0101";
        String end = positionLoc + rows_n + cols_n;
        //判断是否已使用
        String sql1 = "select count(*) from pa_product_point where status <> '" + Sysconst.POINT_STATUS_INSTALLED
                + "' and position_id = '" + area.getId() + "' ";
        Integer used = jdbcTemplate.queryForObject(sql1, Integer.class);
        ParamPreconditions.checkArgument(used == null || used <= 0, CodeEnum.FAIL.getCode(), "位置使用中");
        //初始化位置状态
        String sql2 = "update pa_product_point set status = '" + Sysconst.POINT_STATUS_UNINSTALL + "'" +
                " where status = '" + Sysconst.POINT_STATUS_INSTALLED + "' and position_id = '" + area.getId() + "'";
        jdbcTemplate.update(sql2);
        //更新位置状态
        String sql = "update pa_product_point set status = '" + Sysconst.POINT_STATUS_INSTALLED + "'" +
                " where location_no >= '" + start + "' and location_no <= '" + end + "'";
        jdbcTemplate.update(sql);

        area.setName(name);
        area.setCameraIp(cameraIp);
        area.setUpdatetime(DateTimes.nowDateTime());
        area = paProductPositionRepository.saveAndFlush(area);
        PaProductPositionDto dto = new PaProductPositionDto();
        BeanUtils.copyProperties(area, dto);
        return dto;
    }

    /**
     * 删除商品位置
     *
     * @param id
     * @return
     */
    public Boolean delete(String id) {
        log.info("删除商品位置id:{}", id);
        List<PaProductDto> list = paProductService.query(null, null, null, id, null, null, null, null, null, null,null);
        ParamPreconditions.checkArgument(list == null || list.size() == 0, CodeEnum.FAIL.getCode(), "商品绑定改类别，不能删除");
        PaProductPosition position = paProductPositionRepository.findOne(id);
        if (position == null || Sysconst.ENABLED_FALSE.equals(position.getState())) return true;
        position.setState(Sysconst.ENABLED_FALSE);
        paProductPositionRepository.saveAndFlush(position);
        return true;
    }
    /*new_edition 逻辑删除商品位置*/

    /**
     * 删除商品位置
     *
     * @param id
     * @return
     */
    public Boolean delete1(String id) {
        log.info("删除商品位置id:{}", id);
        /*校验位置是否绑定商品*/
        String sql = "select count(*) from pa_product where state=0 and FIND_IN_SET('" + id + "',position_ids) > 0";
        Integer exist = jdbcTemplate.queryForObject(sql, Integer.class);
        ParamPreconditions.checkArgument(exist == null || exist == 0, CodeEnum.FAIL.getCode(), "该位置已绑定商品，无法删除");
        /*校验位置是否存正在供灯中*/
//		String str = "'" + Sysconst.POINT_STATUS_LOCK + "','"+Sysconst.POINT_STATUS_LOCK + "'";
//		String sql1 = "select count(1) from pa_product_point where position_id = '"+id+"' and status in("+str+")";
//		Integer used = jdbcTemplate.queryForObject(sql1, Integer.class);
//		ParamPreconditions.checkArgument(used == null || used <= 0, CodeEnum.FAIL.getCode(), "该位置供灯中，无法删除");
        /*执行逻辑删除*/
        PaProductPosition position = paProductPositionRepository.findOne(id);
        if (position == null || Sysconst.ENABLED_FALSE.equals(position.getState())) return true;
        position.setState(Sysconst.ENABLED_FALSE);
        paProductPositionRepository.saveAndFlush(position);
        return true;
    }

    /*new_edition 新增区域、位置是否存在校验方法*/
    public String extractNoByStr(String str) {
        String result = "";
        char first = str.charAt(0);
        result = String.valueOf(first);
        ParamPreconditions.checkArgument(Character.isDigit(first), CodeEnum.FAIL.getCode(), "首字符非阿拉伯数字");
        ParamPreconditions.checkArgument(Integer.parseInt(result) > 0, CodeEnum.FAIL.getCode(), "编号需大于0");
        for (int i = 1; i < str.length(); i++) {
            if (Character.isDigit(str.charAt(i)))
                result = result + str.charAt(i);
            else
                break;
        }
        ParamPreconditions.checkArgument(result.length() <= 2, CodeEnum.FAIL.getCode(), "需两位数");
        return result;
    }
	/**
	 * 加载所有位置
	 * @return
	 */
	public void loadProductPositions(){
//		String sql = "select substring(name,1,2) name from pa_product_position where state = 0 group by name";
//		List<String> list = jdbcTemplate.query(sql,(RowMapper<String>)(rs, rowNum) ->{
//				String pos = rs.getString(0);
//				 log.info("pos:{}", pos);
//				return pos;
//		});
		POSITIONS.clear();
		List<String> strs = paProductPositionRepository.loadProductPositions();
//		List<String> strs = list.stream().map(PaProductPosition::getName).collect(Collectors.toList());
//		strs = strs.stream().map(name -> name.substring(0, 2)).collect(Collectors.toList());
		POSITIONS.addAll(strs);
		MAXPILLARS = POSITIONS.size();
	}
}
